﻿/* 2013/6/27 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Cosmos.Media
{
    /// <summary>
    /// Represents ID3V1 tag.
    /// </summary>
    class ID3V1
    {
        public const int TotalLength = 128;
        public const int HeaderLength = 3;
        public const int TitleLength = 30;
        public const int ArtistLength = 30;
        public const int AlbumLength = 30;
        public const int YearLength = 4;
        public const int CommentLength = 28;

        private static readonly byte[] AvailableHeader = 
            new byte[] { (byte)'T', (byte)'A', (byte)'G' };


        /// <summary>
        /// Header of the music, 3 bytes.
        /// </summary>
        public byte[] Header
        {
            get;
            private set;
        }

        /// <summary>
        /// Title of the music, 30 bytes.
        /// </summary>
        public byte[] Title
        {
            get;
            private set;
        }

        /// <summary>
        /// Artist of the music, 30 bytes.
        /// </summary>
        public byte[] Artist
        {
            get;
            private set;
        }

        /// <summary>
        /// Album of the music, 30 bytes.
        /// </summary>
        public byte[] Album
        {
            get;
            private set;
        }

        /// <summary>
        /// Year of the music, 4 characters.
        /// </summary>
        public byte[] Year
        {
            get;
            private set;
        }

        /// <summary>
        /// Comment of the music, 28 bytes.
        /// </summary>
        public byte[] Comment
        {
            get;
            private set;
        }

        /// <summary>
        /// Reserved bit, 1 byte.
        /// </summary>
        public byte Reserve
        {
            get;
            set;
        }

        /// <summary>
        /// Track bit,1 byte.
        /// </summary>
        public byte Track
        {
            get;
            set;
        }

        /// <summary>
        /// Genre bit,1 byte.
        /// </summary>
        public byte Genre
        {
            get;
            set;
        }

        /// <summary>
        /// Initializes an instance of ID3V1 class.
        /// Extracts information from a byte array whose length is 128.
        /// </summary>
        public ID3V1()
        {
            Header = new byte[HeaderLength];
            Title = new byte[TitleLength];
            Artist = new byte[ArtistLength];
            Album = new byte[AlbumLength];
            Year = new byte[YearLength];
            Comment = new byte[CommentLength];
        }

        /// <summary> 
        /// Loads ID3V1 tag information from a byte array.
        /// </summary> 
        /// <param name = "bytes">Bytes of ID3V1 tags, which are extracted from end of file.</param>
        public void Load(byte[] bytes)
        {
            int i;
            int j;
            int position = 0;
            int currentIndex = 0;

            // Extracts header.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.HeaderLength;
                i++, j++)
            {
                Header[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts title.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.TitleLength;
                i++, j++)
            {
                Title[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts artist.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.ArtistLength;
                i++, j++)
            {
                Artist[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts album.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.AlbumLength;
                i++, j++)
            {
                Album[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts year.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.YearLength;
                i++, j++)
            {
                Year[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts comments.
            for (i = currentIndex, j = 0; i < currentIndex + ID3V1.CommentLength;
                i++, j++)
            {
                Comment[j] = bytes[i];
                position++;
            }
            currentIndex = position;

            // Extracts reserved bits. 
            Reserve = bytes[++position];
            Track = bytes[++position];
            Genre = bytes[++position];
        }

        public bool isAvailable
        {
            get
            {
                return Header.SequenceEqual(AvailableHeader);
            }
        }
    }
}
